/**
 * 
 */
package de.muyat.kablosuzizci.istemci;

import tr.muyat.kablosuzizci.istemci.yardimcilarmodulu.FormatHatasi;
import tr.muyat.kablosuzizci.istemci.yardimcilarmodulu.Kullanislilar;

/**
 * 3x3'luk bir rotasyon matrisini temsil eder.
 * @author Dzhoshkun Ismail Shakir
 *
 */
public class RotasyonMatrisi {
	private float[][] matris = new float[3][3];
	
	/**
	 * Bu sinifin her objesi bu kadar byte olarak serilestirilir.
	 */
	public static final int DIZIN_BYTE_UZUNLUGU = 3 * 3 * 4;
	
	/**
	 * 
	 */
	@SuppressWarnings("unused")
	private RotasyonMatrisi() {
		
	}

	/**
	 * 
	 * @param matrisi 9 elemanlik, satirlarin oncelendigi (row-first) matris gosterimi
	 * @throws IllegalArgumentException
	 */
	public RotasyonMatrisi(float[] matris) throws IllegalArgumentException {
		if (matris.length!=9)
			throw new IllegalArgumentException();
		for (int i=0; i<3; i++) {
			for (int j=0; j<3; j++) {
				this.matris[i][j] = matris[i*3+j];
			}
		}
	}
	
	/**
	 * Verilen {@link Dondurulebilir3f} nesneyi dondurur.
	 * @param dondurulecek bu nesnenin degerleri degisir
	 * @throws IllegalArgumentException
	 */
	public void dondur(Dondurulebilir3f dondurulecek) throws IllegalArgumentException {
		float[] vektor = dondurulecek.vektorlestir();
		if (vektor.length!=3)
			throw new IllegalArgumentException();
		float[] sonuc = new float[3];
		for (int i=0; i<3; i++)
			sonuc[i] = matris[i][0] * vektor[0] + matris[i][1] * vektor[1] + matris[i][2] * vektor[2];
		dondurulecek.vektordenKopyala(sonuc);
	}
	
	/**
	 * 
	 * @return oryantasyon bilgilerinin byte dizini olarak serilestirilmis hali
	 */
	public byte[] serilestir() {
		byte[] serilestirilmisRotasyonMatrisi = new byte[DIZIN_BYTE_UZUNLUGU];
		for (int i=0; i<matris.length; i++) {
			for (int j=0; j<matris[i].length; j++) {
				byte[] deger = Kullanislilar.byteDizinineDonustur(matris[i][j]);
				System.arraycopy(deger, 0, serilestirilmisRotasyonMatrisi, 4*(i*matris[j].length+j), 4);
			}
		}
		return serilestirilmisRotasyonMatrisi;
	}
	
	/**
	 * 
	 * @param serilestirilmisRotasyonMatrisi
	 * @param offset verilen dizinin neresinden baslayayim okumaya?
	 * @return parametre olarak girilen byte dizininden elde edilen obje
	 * @throws FormatHatasi
	 */
	public static RotasyonMatrisi seridenOku(byte[] serilestirilmisRotasyonMatrisi, int offset) throws FormatHatasi {
		float[] matris = new float[3*3];
		try {
			for (int i=0; i<3; i++) {
				for (int j=0; j<3; j++) {
					byte[] deger = new byte[4];
					System.arraycopy(serilestirilmisRotasyonMatrisi, offset+4*(i*3+j), deger, 0, 4);
					matris[i*3+j] = Kullanislilar.floataDonustur(deger);
				}
			}
			return new RotasyonMatrisi(matris);
		}
		catch (ArrayIndexOutOfBoundsException e) {
			throw new FormatHatasi();
		}
	}
	
	/**
	 * Bu nesnenin butun degerleri {@code baska} bir nesneden kopyalanir. Surekli yeni
	 * nesne yaratmamak icin boyle bir hack gerekti.
	 * @param baska
	 */
	public void kopyala(RotasyonMatrisi baska) {
		for (int i=0; i<3; i++)
			for (int j=0; j<3; j++)
				this.matris[i][j] = baska.matris[i][j];
	}
}
